UPS XML Rates v1.6.1 for osCommerce 2.3.4 2017-04-11

Original Copyright (c) 2003 Torin Walker, torinwalker@rogers.com

===============================================================================
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program.
If not, you may obtain one by writing to and requesting one from

	The Free Software Foundation, Inc.,
	59 Temple Place, Suite 330,
	Boston, MA 02111-1307 USA
=============================================================================== 

---------------
SUPPORT THREAD: http://forums.oscommerce.com/index.php?showtopic=49382&view=getlastpost
---------------

--------------
Description
--------------

This shipping module provides the osCommerce community with the XML version of the UPS Rates and Services gateway. This version can be used all over the world. UPS still maintains a HTML version that can only be used for shops that reside in the US. There used to be a standard ups.php shipping module in osC that used this HTML interface. You can still find an amended version (UPS Choice) of that module in the add-on section: http://addons.oscommerce.com/info/528

In the admin you can exclude certain shipping options from being shown to the customer.

Perhaps you already found there are quite a few files in the folder "catalog" that you don't recognize as belonging to a standard shipping module. This is because UPSXML can (and should) be extended with dimensional support (see install_dimensional_support.txt in the folder dimensional_support).
First install UPSXML and check that it works before proceeding with dimensional support. Installing dimensional support is HIGHLY RECOMMENDED since UPS now charges dimensional weight for ALL methods. The rate quotes your web site will return will be much more likely to be reasonably accurate if you use dimensional support. Installing the split product support (found in the folder dimensional_support) is recommended if you have any products that come packaged in multiple boxes for a single product.

-------------------------------------------------
Features UPSXML *does NOT have*
-------------------------------------------------

UPSXML does not create shipping labels or inform UPS that a package should be picked up. It also does not feature integration with UPS Worldship software (although there are forum members who have succeeded in that by transferring data to another database and then importing it, see also the add-ons and search with keyword Worldship).
It also has nothing to do with package tracking. It only gets shipping quotes from UPS (see example_response.jpg for how it can look on checkout_shipping.jpg (when Time in Transit information is set to "Not" in the admin).


----------------------------
**IMPORTANT** WHEN UPGRADING 
----------------------------

When upgrading from a previous version, you *HAVE* to go into the admin, modules shipping, make a note of the settings (especially Access Key, Username and Password) and "remove" UPSXML. Then upload the new upsxml.php files (both the shipping module and language file, might be needed in more than one language!) and then install again. 
A number of configuration keys have changed in the new module so you can't de-install the old ones with the new 1.6.1 version and several new keys have been added.
If you used version 1.5 or older than you will also need to replace the catalog/includes/classes/xml.php and admin/includes/classes/xml.php with the new files: xml.php (see also step 2 below).

=============================
Changes version 1.6.1
=============================
Files that have changed:
catalog/includes/modules/shipping/upsxml.php
catalog/includes/languages/english/modules/shipping/upsxml.php
catalog/includes/classes/packing.php
catalog/includes/classes/xml.php
catalog/admin/includes/classes/xml.php
catalog/admin/includes/languages/english/shipping_boxes_used.php
catalog/admin/shipping_boxes_used.php

To upgrade an earlier version of UPSXML to version 1.6.1 you must follow the following steps:
1) Log in to Admin and go to Modules Shipping.
2) Make note of the current settings for your UPSMXL module. In particular be sure to record your Access Key, User Name and Password.
3) Once you have safely recorded your settings click on the REMOVE button for the old version of the module to remove the existing configuration settings and confirm the removal. This is required because several have been changed and several more have been added.
4) Only then should you replace any files. Replace both xml.php class files, the shipping module file and module language file. NOTE: The new language file will not work with older versions of the module and older versions of the module will not work with the new language file. If you use the packaging class (which is recommended) then replace the packaging class file. If you use the Shipping Boxes Used tool then replace those files as well.
5) Once the new versions of the PHP files are uploaded go to Modules Shipping in Admin and INSTALL the UPSXML module.
6) Reenter your Access Key, User Name and Password, enter the shipping from address information and customize any other settings as needed and save. You updated module is now ready to use.

===============================================================================
INSTALLATION
===============================================================================

--------
STEP 1
--------
BACKUP your database and any files that will be amended before beginning

Run the three queries found in (or use the file itself) the included sql file: configuration_shipping.sql to add three configuration keys to the table configuration. Then configure them in Admin->Configuration->Shipping/Packaging:

Dimensions Support (leave at No for the time being, read install_dimensional_support.txt in the folder dimensional_support for further info)
Unit Weight (change the default LBS to KGS if needed)
Unit Length (change the default IN to CM if needed)

--------
STEP 2
--------
Extract the files to their appropriate locations. The files needed are:

  catalog/admin/includes/classes/xml.php
  catalog/includes/classes/xml.php
  catalog/includes/languages/english/modules/shipping/upsxml.php
  catalog/includes/modules/shipping/upsxml.php

NOTE: If you have already installed a version of UPSXML older than 1.6 you need to replace all of these files as the original xml.php and xml_5.php class files have been combined into one file and the module has been modified accordingly.

--------
STEP 3 *** If you have already installed USPS Methods or UPS Choice, you can skip this step
--------

In catalog/admin/modules.php

*****************************************
Find This code somewhere around line 48:
*****************************************

  if (tep_not_null($action)) {
    switch ($action) {
      case 'save':
        reset($HTTP_POST_VARS['configuration']);
        while (list($key, $value) = each($HTTP_POST_VARS['configuration'])) {

***********************************************
INSERT THE FOLLOWING CODE AFTER THE ABOVE LINE:
***********************************************

          if (is_array($value) ) {
            $value = implode( ", ", $value);
		        $value = preg_replace ("/, --none--/", "", $value);
		      }

****************************
SO IT SHOULD LOOK LIKE THIS:
****************************

if (tep_not_null($action)) {
    switch ($action) {
      case 'save':
        reset($HTTP_POST_VARS['configuration']);
        while (list($key, $value) = each($HTTP_POST_VARS['configuration'])) {
          if (is_array($value) ) {
            $value = implode( ", ", $value);
		        $value = preg_replace ("/, --none--/", "", $value);
		      }
          tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . $value . "' where configuration_key = '" . $key . "'");
        }
        tep_redirect(tep_href_link(FILENAME_MODULES, 'set=' . $set . '&module=' . $HTTP_GET_VARS['module']));
        break;
      case 'install':


NOTE 1: if you fail to do this step you will get the following error message when editing UPS XML in the admin:

Warning: constant() [function.constant]: Couldn't find constant UPSXML_Array in /path/to/your/shop_root/includes/modules/shipping/upsxml.php on line 1010

NOTE 2: if your settings do not save change the line 

        while (list($key, $value) = each($HTTP_POST_VARS['configuration'])) {

to:

        foreach($_POST['configuration'] as $key => $value) {


--------
STEP 4
--------
In admin, choose Modules->Shipping, and activate the new United Parcel Service (XML) module.
Edit the module and set your service options:

	UPS Rates account access key (obtain from UPS)
	UPS Rates account username (obtain from UPS)
	UPS Rates account password (obtain from UPS)
	Pickup method
	Packaging Type
	Customer Classification Code
	Shipping Origin (determines what products names are shown based on origin)
  Shipper Name (optional)
  Shipper Address Line 1 (optional but recommended)
  Shipper Address Line 2 (optional)
  Shipper Address Line 3 (optional)
	Origin City (required for some countries)
	Origin State/Province (two letter ISO 3166 code)
	Origin Country (two letter ISO 3166 code)
	Origin Zip/Postal Code
	Test or Production mode
  Quote Type
  Negotiated Rates
  UPS Account Number (required if you want to use SurePost)
  Manual Negotiated Rate
  Handling Type
  Flat Handling Fees Charged
	Handling Fee
	Enable Insurance
  UPS Currency Code
	Tax Class
	Shipping Zone (leave at --none-- to use for all shipping zones)
	Sort order of display
	Disallowed shipping methods
  Enable UPS SurePost
  Maximum Value by SurePost (SurePost will not be quoted for packages worth more than this setting)
  Shipping Delay
  Email UPS errors (to the shop owner)
  Time in Transit View Type
  Store Processes Orders
  UPS Picks Up
  UPS Holidays
  Display Weight (for example: (2 pkg(s), 28 lbs total) after United Parcel Service, first line)
  Require Signature
  Signature Threshold
  Adult Signature Threshold

If you have any questions regarding the above settings, please refer to the documentation provided to you by UPS when you signed up for and received your access key. If you still have questions, then post to the forums in the support thread:
http://forums.oscommerce.com/index.php?showtopic=49382&hl=

Note that Customer Classification Code and Pickup methods are only used when the Shipping Origin is US! So don't bother with it if that is not the case.

--------
STEP 5
--------
Test by setting your customer destination to all sorts of different places, and running through the shipping process several times. Please test thoroughly before committing to its use.

If you fail to get quotes, an error message will usually tell you why. Make sure your origin information is correct, and use the proper two-letter codes for your country and state/province.

An apparently common error is one involving certificate verification. For this some lines must be uncommented around line 665-668:

            // uncomment the next line if you get curl error 60: error setting certificate verify locations
            // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
            // uncommenting the next line is most likely not necessary in case of error 60
            // curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);


If you STILL don't get any quotes, you can enable logging which will record the request/response of the transactions and any cURL errors. Look for, uncomment, and change (e.g. to your own full path) the line in upsxml.php (line 133):

//        $this->logfile = '/srv/www/htdocs/catalog/includes/modules/shipping/upsxml.log';

example of a full path:
'/home/yoursite/public_html/catalog/includes/modules/shipping/upsxml.log';

Change the location of the log to something you can read (don't forget to give the file write permissions 664), create an empty file "upsxml.log" on that location, and give the shopping cart a whirl. Your request/response will eventually show up there.

If cURL is not compiled into PHP (Windows users (?) and some Linux users) you can change line 139 to : $this->use_exec = '1'; Using exec() cURL from the command line interface (CLI) is then used. See for more information "Changes from 1.1.3 to 1.1.4" in the changes.txt file.
If exec() is disabled and logging is enabled, this will be logged also.

If cURL is not available either way this shipping module will not work because for a https connection with the UPS servers curl is needed. User names and passwords are sent, so a secure connection is important. UPS will not allow you to use http (for the above mentioned reason).

To test UPSXML without having cURL working or having the user names, access keys etc. from UPS set the Time in Transit View Type in the admin to "Not" and follow the instructions, comment and uncomment some lines around line 617-626. Upload the included example_response.xml file, change the path on line 616 to reflect the path on your server and go to checkout with something in the shopping cart. The checkout shipping page should show the shipping methods and prices in the file example_response.jpg.

--------
STEP 6
--------

A few lines below the line 133:
//        $this->logfile = '/srv/www/htdocs/catalog/includes/modules/shipping/upsxml.log';
you will find another line (line 135):
//      $this->ups_error_file = '/srv/www/htdocs/catalog/includes/modules/shipping/upsxml_error.log';

Do as in step 5: create an empty document of that name, set the path to what you want and make it writable for the server. This file will only log the error messages that are returned by UPS. The file in step 5 will grow very big, very quickly. This file is only one line per UPS module (TimeInTransit and Rates are used). Together with the admin setting for getting those errors emailed, you can keep tabs of what is happening. The customer id is logged too, so you can contact them if necessary.

--------
STEP 7
--------

If you have installed Separate Pricing Per Customer (SPPC), add this shipping module to the enabled ones for the customer groups.

----------------------------
STEP 8 ** OPTIONAL **
----------------------------

Steve Lionel (stevel) pointed out that checkout_shipping.php does the whole get quote procedure (contacting the website for shipping quotes like UPSP, UPS, FedEx etcetera) again on pressing the Continue button (action=process). Since that is rather a time waste and waste of resources you can add the following code to avoid this

File: checkout_shipping.php

Line 112-117

**REPLACE**

          if ($shipping == 'free_free') {
            $quote[0]['methods'][0]['title'] = FREE_SHIPPING_TITLE;
            $quote[0]['methods'][0]['cost'] = '0';
          } else {
            $quote = $shipping_modules->quote($method, $module);
          }

**WITH**

          if ($shipping == 'free_free') {
            $quote[0]['methods'][0]['title'] = FREE_SHIPPING_TITLE;
            $quote[0]['methods'][0]['cost'] = '0';
          } else { // not free shipping
            // check if the cart and send to address haven't changed in the mean time
             if (isset($_SESSION['shipping_quotes']) && $_SESSION['shipping_quotes']['cartID'] == $cartID && $_SESSION['shipping_quotes']['sendto'] == $sendto) {
              foreach ($_SESSION['shipping_quotes']['quotes'] as $array_key => $shipping_quote) {
                if ($shipping_quote['id'] == $module) {
                  foreach ($shipping_quote['methods'] as $subarray_key => $method_array) {
                    if ($method_array['id'] == $method) {
                       $quote[] = array('id' => $module, 'module' => $shipping_quote['module'], 'methods' => array($method_array));
                       break;
                    } // end if ($method_array['id'] == $method)
                  } // end foreach ($shipping_quote['methods'] as $subarray_key => $method_array)
                  break; // found shipping quote in session
                } // end if ($shipping_quote['id'] == $module)
              } // end foreach ($_SESSION['shipping_quotes']['quotes']...
// if for some reason the quote is not found in the session so $quote is not set here we get our quotes again
              if (!isset($quote)) {
                $quote = $shipping_modules->quote($method, $module);
              } // end if (!isset($quote))
            } else { 
              $quote = $shipping_modules->quote($method, $module);
            }
          }

Line 140-142 (originally, now 159-160)

**REPLACE**

// get all available shipping quotes
  $quotes = $shipping_modules->quote();

**WITH**

// get all available shipping quotes
  $quotes = $shipping_modules->quote();
  if (!tep_session_is_registered('shipping_quotes')) tep_session_register('shipping_quotes');
  $shipping_quotes = array('cartID' => $cartID, 'sendto' => $sendto, 'quotes' => $quotes);

Additionally it will need to be unset in checkout_process.php. Find line 296-301 and add the indicated line:

// unregister session variables used during checkout
  tep_session_unregister('sendto');
  tep_session_unregister('billto');
  tep_session_unregister('shipping');
  tep_session_unregister('shipping_quotes'); // add this line
  tep_session_unregister('payment');
  tep_session_unregister('comments');


What is does is just store the shipping quotes received in a session variable (so the customer cannot change it) and then access the session variable on action=process instead of getting the quotes again.

----------------------------
STEP 9 ** FOR GODADDY HOSTING ONLY **
----------------------------

A number of people using GoDaddy for their hosting have found that the UPSXML module times out when getting rate quotes. This is due to the fact that GoDaddy uses a special setup for the https connections, namely a proxy server.

In that case (haven't tested this, but this is a compilation from the postings and uploads) change a part of the code in catalog/includes/modules/shipping/upsxml.php

Line 89

**CHANGE**

        $this->timeout = '60';

**TO**

        $this->timeout = '120';


Line 665-673

**REPLACE**

            // uncomment the next line if you get curl error 60: error setting certificate verify locations
            // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
            // uncommenting the next line is most likely not necessary in case of error 60
            // curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
            curl_setopt($ch, CURLOPT_TIMEOUT, (int)$timeout);

**WITH**

// BOF GODADDY STUFF
            // uncomment the next line if you get curl error 60: error setting certificate verify locations
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
            // uncommenting the next line is most likely not necessary in case of error 60
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
            curl_setopt ($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);
// change this->timeout = '60' around line 90 to this->timeout = '120' for GoDaddy hosting
            curl_setopt($ch, CURLOPT_TIMEOUT, (int)$timeout);
            curl_setopt ($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
            curl_setopt ($ch, CURLOPT_PROXY, "http://proxy.shr.secureserver.net:3128");
// EOF GODADDY STUFF

----------------------------
STEP 10 ** RECOMMENDED **
----------------------------
This module supports the dimensions modifications proposed by Tom St. Croix's Canada Post 3.1 Module. 
The shipping module can then employ length, width, height, dimensions in either centimeters or inches, and weight in pounds or kilograms. Dimensional support is somewhat involved, and is further detailed in dimensions.txt, but offers much more accurate shipping that can save you money.

Additional files needed for dimensional support and packaging addition:

    catalog/includes/classes/packing.php
    catalog/admin/packaging.php
    catalog/admin/includes/languages/english/packaging.php
